package com.example.userservice.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.constant.RoleConstant;
import com.example.common.dto.*;
import com.example.common.enums.ErrorCodeEnum;
import com.example.common.event.OperationLogEvent;
import com.example.common.exception.BusinessException;
import com.example.common.feign.PermissionFeignClient;
import com.example.common.util.IpUtils;
import com.example.common.util.JwtUtils;
import com.example.userservice.entity.User;
import com.example.userservice.mapper.UserMapper;
import com.example.userservice.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;
    private final PermissionFeignClient permissionFeignClient;
    private final RocketMQTemplate rocketMQTemplate;
    private final HttpServletRequest request;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Long> register(UserRegisterDTO registerDTO) {
        // 1. 检查用户名是否已存在
        User existUser = userMapper.findByUsername(registerDTO.getUsername());
        if (existUser != null) {
            throw new BusinessException(ErrorCodeEnum.USERNAME_EXISTS, "用户名已存在");
        }

        // 2. 创建用户
        User user = new User();
        BeanUtils.copyProperties(registerDTO, user);
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        user.setGmtCreate(LocalDateTime.now());

        // 3. 分库分表插入用户数据
        int insertResult = userMapper.insert(user);
        if (insertResult <= 0) {
            throw new BusinessException(ErrorCodeEnum.USER_REGISTER_FAILED, "用户注册失败");
        }

        // 4. 调用权限服务绑定角色（分布式事务部分）
        ApiResponse<Void> bindResponse = permissionFeignClient.bindDefaultRole(user.getUserId());
        if (!bindResponse.isSuccess()) {
            throw new BusinessException(ErrorCodeEnum.BIND_ROLE_FAILED, "角色绑定失败: " + bindResponse.getMessage());
        }

        // 5. 发送注册日志消息
        OperationLogEvent event = new OperationLogEvent();
        event.setUserId(user.getUserId());
        event.setAction("USER_REGISTER");
        event.setIp(IpUtils.getIpAddr(request));
        event.setDetail("注册用户: " + user.getUsername());

        try {
            String jsonMessage = JSON.toJSONString(event);
            rocketMQTemplate.convertAndSend("user-operation-log", jsonMessage);
            log.info("用户注册日志消息发送成功: {}", jsonMessage);
        } catch (Exception e) {
            log.error("用户注册日志发送失败", e);
            // 日志发送失败不影响主流程
        }

        return ApiResponse.success(user.getUserId());
    }

    @Override
    public ApiResponse<String> login(LoginDTO loginDTO) {
        // 1. 查询用户
        User user = userMapper.findByUsername(loginDTO.getUsername());
        if (user == null) {
            throw new BusinessException(ErrorCodeEnum.USER_NOT_FOUND, "用户不存在");
        }

        // 2. 验证密码
        if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
            throw new BusinessException(ErrorCodeEnum.PASSWORD_ERROR, "密码错误");
        }

        // 3. 获取用户角色
        ApiResponse<String> roleResponse = permissionFeignClient.getUserRoleCode(user.getUserId());
        if (!roleResponse.isSuccess()) {
            throw new BusinessException(ErrorCodeEnum.GET_USER_ROLE_FAILED, "获取用户角色失败");
        }
        String role = roleResponse.getData();

        // 4. 生成JWT令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getUserId());
        claims.put("username", user.getUsername());
        claims.put("role", role);

        String token = JwtUtils.generateToken(claims);

        // 5. 发送登录日志
        OperationLogEvent event = new OperationLogEvent();
        event.setUserId(user.getUserId());
        event.setAction("USER_LOGIN");
        event.setIp(IpUtils.getIpAddr(request));
        event.setDetail("用户登录: " + user.getUsername());
        String jsonMessage = JSON.toJSONString(event);
        rocketMQTemplate.convertAndSend("user-operation-log", jsonMessage);
        log.info("用户登录日志消息发送成功: {}", jsonMessage);

        return ApiResponse.success(token);
    }

    @Override
    public ApiResponse<Page<User>> listUsers(int pageNum, int pageSize) {
        // 获取当前用户信息
        Long currentUserId = getCurrentUserId();
        String currentUserRole = getCurrentUserRole();

        // 构建查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();

        if (RoleConstant.USER.equals(currentUserRole)) {
            // 普通用户只能查自己
            queryWrapper.eq("user_id", currentUserId);
        } else if (RoleConstant.ADMIN.equals(currentUserRole)) {
            // 管理员只能查普通用户
            queryWrapper.eq("role", RoleConstant.USER);
        }
        // 超管无限制

        // 执行分页查询
        Page<User> page = new Page<>(pageNum, pageSize);
        Page<User> resultPage = userMapper.selectPage(page, queryWrapper);

        // 隐藏敏感信息
        resultPage.getRecords().forEach(u -> u.setPassword(null));

        return ApiResponse.success(resultPage);
    }

    @Override
    public ApiResponse<User> getUserById(Long userId) {
        // 1. 获取当前用户信息
        Long currentUserId = getCurrentUserId();
        String currentUserRole = getCurrentUserRole();

        // 2. 查询目标用户
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCodeEnum.USER_NOT_FOUND, "用户不存在");
        }

        // 3. 权限检查
        if (RoleConstant.USER.equals(currentUserRole)) {
            // 普通用户只能查看自己
            if (!currentUserId.equals(userId)) {
                throw new BusinessException(ErrorCodeEnum.PERMISSION_DENIED, "无权限查看其他用户信息");
            }
        } else if (RoleConstant.ADMIN.equals(currentUserRole)) {
            // 管理员只能查看普通用户和自己
            if (!RoleConstant.USER.equals(user.getRole()) && !currentUserId.equals(userId)) {
                throw new BusinessException(ErrorCodeEnum.PERMISSION_DENIED, "无权限查看此用户信息");
            }
        }
        // 超管没有限制

        // 4. 隐藏敏感信息
        //user.setPassword(null);
        return ApiResponse.success(user);
    }

    @Override
    @Transactional
    public ApiResponse<Void> updateUser(UserUpdateDTO updateDTO) {
        // 1. 获取当前用户信息
        Long currentUserId = getCurrentUserId();
        String currentUserRole = getCurrentUserRole();
        Long targetUserId = updateDTO.getUserId();

        // 2. 权限验证
        validateUserUpdatePermission(currentUserId, currentUserRole, targetUserId);

        // 3. 更新用户信息
        User updateUser = new User();
        BeanUtils.copyProperties(updateDTO, updateUser);

        int result = userMapper.updateById(updateUser);
        if (result <= 0) {
            throw new BusinessException(ErrorCodeEnum.USER_UPDATE_FAILED, "更新用户信息失败");
        }

        // 4. 发送更新日志
        OperationLogEvent event = OperationLogEvent.builder()
                .userId(currentUserId)
                .action("USER_UPDATE")
                .ip(IpUtils.getIpAddr(request))
                .detail("更新用户信息: " + targetUserId)
                .build();
        String jsonMessage = JSON.toJSONString(event);
        rocketMQTemplate.convertAndSend("user-operation-log", jsonMessage);

        return ApiResponse.success(null);
    }

    @Override
    @Transactional
    public ApiResponse<Void> resetPassword(PasswordResetDTO resetDTO) {
        // 1. 获取当前用户信息
        Long currentUserId = getCurrentUserId();
        String currentUserRole = getCurrentUserRole();
        Long targetUserId = resetDTO.getUserId();

        // 2. 权限验证
        validatePasswordResetPermission(currentUserId, currentUserRole, targetUserId);

        // 3. 更新密码
        User updateUser = new User();
        updateUser.setUserId(targetUserId);
        updateUser.setPassword(passwordEncoder.encode(resetDTO.getNewPassword()));

        int result = userMapper.updateById(updateUser);
        if (result <= 0) {
            throw new BusinessException(ErrorCodeEnum.PASSWORD_RESET_FAILED, "重置密码失败");
        }

        // 4. 发送密码重置日志
        OperationLogEvent event = OperationLogEvent.builder()
                .userId(currentUserId)
                .action("PASSWORD_RESET")
                .ip(IpUtils.getIpAddr(request))
                .detail("重置用户密码: " + targetUserId)
                .build();
        String jsonMessage = JSON.toJSONString(event);
        rocketMQTemplate.convertAndSend("user-operation-log", jsonMessage);

        return ApiResponse.success(null);
    }

    // 权限验证辅助方法
    private void validateUserUpdatePermission(Long currentUserId, String currentUserRole, Long targetUserId) {
        if (RoleConstant.USER.equals(currentUserRole)) {
            // 普通用户只能修改自己
            if (!currentUserId.equals(targetUserId)) {
                throw new BusinessException(ErrorCodeEnum.PERMISSION_DENIED, "无权限修改其他用户信息");
            }
        } else if (RoleConstant.ADMIN.equals(currentUserRole)) {
            // 管理员只能修改普通用户或者自己
            User targetUser = userMapper.selectById(targetUserId);
            if (!RoleConstant.USER.equals(targetUser.getRole()) && !currentUserId.equals(targetUserId)) {
                throw new BusinessException(ErrorCodeEnum.PERMISSION_DENIED, "只能修改普通用户信息");
            }
        }
        // 超管没有限制
    }

    private void validatePasswordResetPermission(Long currentUserId, String currentUserRole, Long targetUserId) {
        if (RoleConstant.USER.equals(currentUserRole)) {
            // 普通用户只能重置自己的密码
            if (!currentUserId.equals(targetUserId)) {
                throw new BusinessException(ErrorCodeEnum.PERMISSION_DENIED, "无权限重置其他用户密码");
            }
        } else if (RoleConstant.ADMIN.equals(currentUserRole)) {
            // 管理员只能重置普通用户密码
            User targetUser = userMapper.selectById(targetUserId);
            if (!RoleConstant.USER.equals(targetUser.getRole()) && !currentUserId.equals(targetUserId)) {
                throw new BusinessException(ErrorCodeEnum.PERMISSION_DENIED, "只能重置普通用户密码");
            }
        }
        // 超管没有限制
    }

    // 辅助方法 - 从SecurityContext获取用户信息
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || authentication.getPrincipal() == null) {
            throw new BusinessException(ErrorCodeEnum.UNAUTHORIZED, "未获取到当前用户信息");
        }

        // 直接处理 Long 类型
        if (authentication.getPrincipal() instanceof Long) {
            return (Long) authentication.getPrincipal();
        }

        // 处理字符串类型
        if (authentication.getPrincipal() instanceof String) {
            try {
                return Long.parseLong((String) authentication.getPrincipal());
            } catch (NumberFormatException e) {
                // 继续尝试其他方式
            }
        }

        // 处理自定义 UserDetails
        if (authentication.getPrincipal() instanceof UserDetails) {
            return Long.parseLong(((UserDetails) authentication.getPrincipal()).getUsername());
        }

        throw new BusinessException(ErrorCodeEnum.UNAUTHORIZED, "不支持的Principal类型: " +
                authentication.getPrincipal().getClass().getName());
    }

    private String getCurrentUserRole() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getAuthorities() != null) {
            return authentication.getAuthorities().iterator().next().getAuthority();
        }
        throw new BusinessException(ErrorCodeEnum.UNAUTHORIZED, "未获取到当前用户角色");
    }
}
